home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Whiteline: delta
/
whiteline CD Series - delta.iso
/
tex
/
tools
/
dvi_300b
/
treiber
/
sources
/
bj200.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-25
|
17KB
|
480 lines
/*
Treiber für Canon BJ200 Drucker für Atari DVI-Treiber (Version 2.30):
Für Quer- und Hochkant!
- DVI-Druckertreiber für Canon BJ200 Drucker. Der Sourcecode entspricht
(immer noch) gröβtenteils der EPSON-Stylus Version.
- WICHTIG: Dieser Treiber erwartet das der Canon BJ in der
____BJ-Emulation____
betrieben wird! Für die EPSON-Emulation kann man den EPSON LQ800
Treiber benutzen. Letzterer bietet nur keine echten 360*360 dpi
Auflösung (Eine Nadel wird in der EPSON-Emulation immer durch zwei
Düsen emuliert) und auch keinen 48 Düsen Druck :-(.
- Bemerkung: Ich habe diesen Treiber nur teilweise getestet!
(Nicht nur) Deshalb:
BENUTZUNG AUF EIGENE GEFAHR. ICH ÜBERNEHME KEINE VERANTWORTUNG
FÜR EVENTUELLE SCHÄDEN, DIE DURCH DIE BENUTZUNG DIESES TREIBERS
VERURSACHT WURDEN. ICH BEHAUPTE AUCH NICHT, DASS DIESES PROGRAMM
IRGENDEINEN ZWECK ERFÜLLT.
WER HIERMIT NICHT EINVERSTANDEN IST, DARF DIESEN TREIBER NICHT
BENUTZEN!!
Verbesserungsvorschläge sind willkommen:
Derzeitige Adresse:
Dietmar Herrendörfer,
Department of Physics,
Trinity College,
Dublin 2
Ireland
email: dhrrndrf@tcd.ie
- Version 1.2
© 1995, Dietmar Herrendörfer.
© Markus Pristovsek, für die Teile, die aus anderen Treibern wurden.
Bem.: Tabulatorabstand auf 4 Zeichen setzen.
*/
/* Weitere Bemerkung: Der Treiber wurde von mir (Markus Pristovsek) in neue Form
eingepaßt. Theoretisch sollte er funktionieren, kann jedoch von mir mangels Drucker
nicht getestet werden. */
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <portab.h>
#include "treiber.h"
/*** Ein paar Parameter: ***/
/*++ Seitenabmessungen - alle Pixelgröβen bezogen auf 360dpi*360dpi: ++*/
#define TOP 43L /* Oberer Rand in Pixeln. */
#define BOTTOM 90L /* Unterer Rand in Pixeln. */
#define LEFT 47L /* Linker Rand in Pixeln. */
#define RIGHT 49L /* Rechter Rand in Pixel. */
#define A4WIDTH 2976L /* A4 Papierbreite in Pixeln. */
#define A4HEIGHT 4209L /* A4 Papierhöhe in Pixeln. */
#define WIDTH (A4WIDTH-LEFT-RIGHT) /* max. Breite einer Grafikseite */
#define HEIGHT (A4HEIGHT-TOP-BOTTOM) /* max. Bitmap Höhe */
#define BUF_SIZE WIDTH*6L+6L+256L /* Gröβe des benötigten Zeilenpuffers. */
/*** Neudefinierte Typen: ***/
typedef struct {
UBYTE id; /* Druckmodusnummer. */
WORD h_dpi; /* Horizontale Auflösung. */
WORD v_dpi; /* Vertikale Auflösung. */
WORD bytes; /* Bytes pro Druckkopf-Spalte. */
} MODI;
/*** Lokale Variablen: ***/
/*++ Drucker Steuercodes und ähnliches Druckerspezifisches: ++*/
static UBYTE init[] = "\033[K\002\000\000\045"/* Reset & 1/360 dpi spacing. */
"\033[\\\004\000\000\000\150\001";
static UBYTE h_step[] = "\033d__"; /* Horizontale Druckkopfbewegung. */
static UBYTE v_step[] = "\034CJ\004_\015"; /* Zeilenvorschub in 360 dpi. */
static UBYTE v_skip[] = "\034CJ\000\200\015"; /* 256/360 Inch Zeilenvorschub. */
static UBYTE g_print[] = "\033[g"; /* Bitmap-Graphik drucken. */
static MODI cbj_mode[]= {{ 0, 60, 60, 1}, /* Canon BJ200 Druckermodi: */
{ 1, 120, 60, 1},
{ 2, 120, 60, 1},
{ 3, 240, 60, 1},
{ 8, 60, 180, 3},
{ 9, 120, 180, 3},
{ 11, 180, 180, 3},
{ 12, 360, 180, 3},
{ 13, 120, 360, 6},
{ 14, 180, 360, 6},
{ 15, 240, 360, 6},
{ 16, 360, 360, 6},
{ 0, 0, 0, 0}}; /* Markiert das Listenende !*/
/****************************************************************************************/
/*** Globale Variablen: ***/
LONG max_puffer_laenge = BUF_SIZE; /* Obergrenze der Gröβe des Druckpuffers. */
/*** Lokale Variable: ***/
static UBYTE prt_buffer[BUF_SIZE]; /* Zwischenspeicher für eine Zeile */
/* Überspringt "Rows" leerzeilen */
void skip_rows( WORD out_channel, LONG rows )
{
v_step[4] = (UBYTE)255; /* Maximal 255 Zeilen pro Vorschub: */
while( rows>255L )
{
print_block( 6L, v_step, out_channel );
rows -= 255L;
}
v_step[4] = (UBYTE)rows; /* und den Rest */
print_block( 6L, v_skip, out_channel );
}
/* 7.10.95 */
/****************************************************************************************/
/* Ausdruck einer Seite als Landscape */
WORD drucke_quer(UBYTE *bitmap_ptr, LONG h_offset, LONG hsize_p, LONG vsize_p, LONG h_dpi, LONG v_dpi, WORD out_channel, WORD flag )
{
UBYTE *bit_ptr, *prt_ptr; /* Pointer in die Bitmap und in den Druckpuffer. */
MODI *mode, *tmp_mode; /* Zeiger auf die Modus-Tabelle. */
LONG hdpi_diff, vdpi_diff; /* Zum Festlegen der Auflösung. */
register LONG tmp; /* Puffer für alles mögliche. */
register LONG hsize_b, hsize_m; /* Druckseitenbreite in Bytes, Bitmapbreite in Bytes. */
register LONG h_pos, rows_to_skip; /* Derzeitige Druck-Zeile, Anzahl leerer Zeilen. */
LONG l_margin, right, left; /* Linker Rand, Zeilenränder. */
LONG prt_columns, prt_bytes; /* Druckspalten pro Zeile, Spaltenhöhe in Bytes. */
int active; /* Ein flag. */
(void)h_offset; /* ignorieren */
/*** Initialisierung: ***/
/*++ Gewünschte Auflösung an vorhandene Auflösungen anpassen: ++*/
/*++ Bem.: Die optimale Anpassung der vertikalen Auflösung geht vor. ++*/
tmp_mode = cbj_mode;
hdpi_diff = vdpi_diff = LONG_MAX; /* Zunächst maximale Abweichung. */
do
{
if( labs( tmp_mode->v_dpi - h_dpi )<hdpi_diff )
{
hdpi_diff = labs(tmp_mode->v_dpi - h_dpi);
vdpi_diff = labs(tmp_mode->h_dpi - v_dpi);
mode = tmp_mode;
}
if( labs( tmp_mode->v_dpi - h_dpi )==hdpi_diff )
{
if( labs( tmp_mode->h_dpi - v_dpi )<vdpi_diff )
{
mode = tmp_mode;
vdpi_diff = labs(tmp_mode->v_dpi - v_dpi);
}
}
}
while( (++tmp_mode)->bytes ); /* bytes == 0 => Ende. */
h_dpi = mode->v_dpi; /* Auflösung ggf. abändern. */
v_dpi = mode->h_dpi;
prt_bytes = mode->bytes;
/*++ Diverse Variablen setzen: ++*/
strcpy(prt_buffer, g_print); /* Bitmap-Graphik Steuerkode kopieren */
hsize_b = (hsize_p < (HEIGHT*h_dpi)/360L) ? (hsize_p + 7L) >> 3 : (HEIGHT*h_dpi)/2880L;
hsize_m = ((hsize_p + 15L) >> 4) << 1; /* -> die 'Bitmap' ist eine gerade Anzahl von Bytes hoch. */
/* Nicht druckbare Ränder überspringen. */
if( flag&1 )
{
bitmap_ptr += (tmp = (((TOP*v_dpi)/360L + 7L) >> 3)) - hsize_m*((LEFT*h_dpi)/360L);
hsize_b -= tmp; /* vertikale Gröβe entsprechend korrigieren. */
}
/* Breite der Seite überprüfen: */
if( vsize_p>(tmp = (WIDTH*v_dpi)/360L) )
vsize_p = tmp;
/*++ Testen ob die Seite leer ist: ++*/
rows_to_skip = 0; /* Zunächst keine leeren Zeilen. */
for( l_margin=0;
ist_next_leer( bitmap_ptr + l_margin, hsize_m, vsize_p) && l_margin < hsize_b;
l_margin++ )
;
/* Leere Druckzeile ? */
if( l_margin==hsize_b )
{
rows_to_skip = hsize_m;
h_pos = hsize_m;
}
/*** Begin des Druckvorgangs: ***/
/*++ Reset: ++*/
if (flag & 1)
print_block( 16L, init, out_channel );
h_pos = 0;
/*++ Bytes im Puffer an den Drucker ausgeben: ++*/
active = TRUE;
while( active && flag&2 )
{
/*++ Leerzeilen gesondert abarbeiten: ++*/
while( h_pos+rows_to_skip < hsize_m && ist_next_leer( bitmap_ptr + rows_to_skip, hsize_b, vsize_p) )
++rows_to_skip;
h_pos += rows_to_skip;
if( h_pos > hsize_b )
rows_to_skip = hsize_b - (h_pos - rows_to_skip);
/* Ist diese Seite ist schon fertig? */
if( TRUE == (active = (h_pos < hsize_b)) )
{
/* Leerzeilen zu überspringen ? */
if( rows_to_skip>0L )
skip_rows( out_channel, (rows_to_skip*2880L)/h_dpi );
/*++ Ränder einstellen: ++*/
for( right=0;
right < vsize_p - 1L && ist_leerzeile(bitmap_ptr + right*hsize_m, prt_bytes);
right++ )
;
--right;
for( left = vsize_p - 1L;
left > right && ist_leerzeile(bitmap_ptr + left*hsize_m, prt_bytes);
left-- )
;
++left;
/* Linker Rand ? */
if( left>0 )
{
left = (left/3)*3; /* Da in (ganzen) 120 dpi Schritten. */
tmp = ((vsize_p - left)*120)/v_dpi;
h_step[2] = (UBYTE)tmp;
h_step[3] = (UBYTE)(tmp >> 8);
print_block(4L, h_step, out_channel);
}
/*++ Daten drucken: ++*/
prt_ptr = prt_buffer + 6;
for( prt_columns=left-right; prt_columns!=0; prt_columns-- )
{
bit_ptr = bitmap_ptr+(prt_columns)*hsize_m;
for( tmp=1; tmp<=prt_bytes; tmp++ )
*prt_ptr++ = *bit_ptr++;
}
prt_columns = left - right;
prt_buffer[3] = (UBYTE)(prt_columns*prt_bytes + 1L);
prt_buffer[4] = (UBYTE)((prt_columns*prt_bytes + 1L) >> 8);
prt_buffer[5] = (UBYTE)mode->id;
/* Überagt Zeile unteren Rand ? */
if( h_pos+prt_bytes>hsize_b )
{
register WORD bit, byte, and_it; /* => Abschneiden. */
bit = (WORD)(h_pos + prt_bytes - hsize_b);
byte = bit >> 3;
and_it = (0x00FF << (bit & 7));
for( rows_to_skip=0L; rows_to_skip<prt_columns*prt_bytes; rows_to_skip++ )
{
if( rows_to_skip%prt_bytes == byte )
prt_buffer[6L + rows_to_skip] &= and_it;
else
if( rows_to_skip%prt_bytes > byte )
prt_buffer[6 + rows_to_skip] = 0;
}
}
print_block( 6L+prt_columns*prt_bytes, prt_buffer, out_channel );
rows_to_skip = prt_bytes;
bitmap_ptr += prt_bytes;
}
}
/*** Seitenende bearbeiten: ***/
if (flag & 4)
print_block(1L, "\014\007", out_channel);
/*** Das war es: ***/
return 0;
}
/* Änderungen 7.10.95, M. Pristovsek */
/****************************************************************************************/
/*** Druckpuffer ausdrucken (für Querdruck wird drucke_quer aufgerufen):
****
**** > bitmap_ptr (UBYTE *) ; Puffer mit den zu druckenden Bytes.
**** > v_offset (LONG) ; vertikale (horizontale) Startposition in der Bitmap.
**** > hsize_p (LONG) ; Breite der Bitmap in Pixeln.
**** > vsize_p (LONG) ; Höhe der Bitmap in Pixeln.
**** > h_dpi (LONG) ; gewünschte horizontale Auflösung.
**** > v_dpi (LONG) ; gewünschte vertikale Auflösung.
**** > out_channel (WORD) ; Ausgabekanal (siehe TOS: 'Fopen')
**** > flag (WORD) ; Bitfeld: 1=Header, 2=Daten, 4=Ende
**** > quer (WORD) ; Querdruck
**** > opt (UBYTE *) ; String mit zus. Optionen (max. 16 Bytes)
***/
WORD drucke( UBYTE *bitmap_ptr, LONG v_offset, LONG hsize_p, LONG vsize_p,
LONG h_dpi, LONG v_dpi, WORD out_channel, WORD flag, WORD quer, UBYTE *opt )
{
/*** Lokale Variablen: ***/
MODI *mode, *tmp_mode; /* Zeiger auf die Modus-Tabelle. */
LONG hdpi_diff, vdpi_diff; /* Zum Festlegen der Auflösung. */
register LONG tmp; /* Puffer für alles mögliche. */
register LONG hsize_b, hsize_m; /* Druckseitenbreite in Bytes, Bitmapbreite in Bytes. */
register LONG v_pos, rows_to_skip; /* Derzeitige Druck-Zeile, Anzahl leerer Zeilen. */
LONG l_margin, right, left; /* Linker Rand, Zeilenränder. */
LONG prt_columns, prt_bits; /* Druckspalten pro Zeile, Spaltenhöhe in Bits. */
int active; /* Ein flag. */
(void)opt; /* ignorieren */
if( quer )
return drucke_quer( bitmap_ptr, v_offset, hsize_p, vsize_p, h_dpi, v_dpi, out_channel, flag );
/*** Initialisierung: ***/
/*++ Gewünschte Auflösung an vorhandene Auflösungen anpassen: ++*/
/*++ Bem.: Die optimale Anpassung der horizontalen Auflösung geht vor. ++*/
tmp_mode = cbj_mode;
hdpi_diff = vdpi_diff = LONG_MAX; /* Zunächst maximale Abweichung. */
do
{
if( labs( tmp_mode->h_dpi - h_dpi )<hdpi_diff )
{
hdpi_diff = labs(tmp_mode->h_dpi - h_dpi);
vdpi_diff = labs(tmp_mode->v_dpi - v_dpi);
mode = tmp_mode;
}
if( labs( tmp_mode->h_dpi - h_dpi )==hdpi_diff )
{
if( labs( tmp_mode->v_dpi - v_dpi )<vdpi_diff )
{
mode = tmp_mode;
vdpi_diff = labs(tmp_mode->v_dpi - v_dpi);
}
}
}
while( (++tmp_mode)->bytes ); /* bytes == 0 => Ende. */
h_dpi = mode->h_dpi; /* Auflösung ggf. abändern. */
v_dpi = mode->v_dpi;
prt_bits = mode->bytes << 3;
/*++ Diverse Variablen setzen: ++*/
strcpy(prt_buffer, g_print); /* Bitmap-Graphik Steuerkode kopieren */
hsize_b = (hsize_p < (WIDTH*h_dpi)/360L) ? (hsize_p + 7L) >> 3 : (WIDTH*h_dpi)/2880L;
hsize_m = ((hsize_p + 15L) >> 4) << 1; /* -> die 'Bitmap' ist eine gerade Anzahl von Bytes weit. */
if( flag&1 )
{ /* Nicht druckbare Ränder überspringen. */
bitmap_ptr += hsize_m*(tmp = (TOP*v_dpi)/360L) + (((LEFT*h_dpi)/360L + 7L) >> 3);
vsize_p -= tmp; /* vertikale Gröβe entsprechend korrigieren. */
}
v_pos = v_offset;
vsize_p += v_offset; /* Höhe der Seite überprüfen: */
if( vsize_p > (tmp = (HEIGHT*v_dpi)/360L) )
vsize_p = tmp;
vsize_p -= v_offset;
--vsize_p;
/*++ Testen ob die Seite leer ist: ++*/
for (l_margin = 0; ist_next_leer(bitmap_ptr + l_margin, hsize_m, vsize_p) && l_margin < hsize_b; l_margin++);
rows_to_skip = 0; /* Zunächst keine leeren Zeilen. */
if( l_margin == hsize_b )
{ /* Leere Druckseite ? */
rows_to_skip = vsize_p - v_pos; /* So tun, als ob das Ende der Seite erreicht ist. */
v_pos = vsize_p;
}
/*** Begin des Druckvorgangs: ***/
/*++ Reset: ++*/
if( flag&1 )
print_block(16L, init, out_channel);
/*++ Bytes im Puffer an den Drucker ausgeben: ++*/
active = TRUE;
while( active && v_pos<vsize_p && flag&2 )
{
/*++ Leerzeilen gesondert abarbeiten: ++*/
while( v_pos < vsize_p && ist_leerzeile(bitmap_ptr, hsize_b) )
{
rows_to_skip++;
v_pos++;
bitmap_ptr += hsize_m;
}
/* Ist diese Seite ist schon fertig? */
if( TRUE==(active=(v_pos<vsize_p)) )
{
/* Leerzeilen zu überspringen ? */
if( rows_to_skip!=0L )
skip_rows( out_channel, (rows_to_skip*360L)/v_dpi );
/*++ Ränder einstellen: ++*/
for( right=hsize_b - 1L;
right > l_margin && ist_next_leer(bitmap_ptr + right, hsize_m, prt_bits);
right-- )
;
++right;
for( left=l_margin;
ist_next_leer(bitmap_ptr + left, hsize_m, prt_bits) && left < right;
left++ )
;
/* Linker Rand ? */
if( left>0 )
{
left = (left/3)*3; /* Da in (ganzen) 120 dpi Schritten. */
tmp = ((left << 3)*120)/h_dpi;
h_step[2] = (UBYTE)tmp;
h_step[3] = (UBYTE)(tmp >> 8);
print_block( 4L, h_step, out_channel );
}
prt_columns = right - left;
/*++ Daten drucken: ++*/
block_it( prt_buffer+6L, bitmap_ptr+left, prt_columns, hsize_m, mode->bytes );
prt_buffer[3] = (UBYTE)(prt_columns*prt_bits + 1L);
prt_buffer[4] = (UBYTE)((prt_columns*prt_bits + 1L) >> 8);
prt_buffer[5] = (UBYTE)mode->id;
/* Überagt Zeile unteren Rand ? */
if (v_pos + prt_bits > vsize_p)
{
register WORD bit, byte, and_it; /* => Abschneiden. */
bit = (WORD)(v_pos + prt_bits - vsize_p);
byte = bit >> 3;
and_it = (0x00FF << (bit & 7));
for( rows_to_skip = 0L; rows_to_skip < prt_columns*prt_bits; rows_to_skip++ )
{
if( rows_to_skip%mode->bytes == byte )
prt_buffer[6L + rows_to_skip] &= and_it;
else
if( rows_to_skip%mode->bytes > byte )
prt_buffer[6 + rows_to_skip] = 0;
}
print_block( 6L+prt_columns*prt_bits, prt_buffer, out_channel);
rows_to_skip = bit;
active = FALSE;
}
else
{
rows_to_skip = prt_bits;
print_block( 6L+prt_columns*prt_bits, prt_buffer, out_channel );
bitmap_ptr += hsize_m * prt_bits;
v_pos += rows_to_skip;
}
}
}
/*** Seitenende bearbeiten: ***/
/* Seite beenden ? */
if( flag&4 )
print_block( 1L, "\014\007", out_channel );
else
{
/* Evt. Rest ausgeben: Nur noch Leerzeilen */
/* Leerzeilen zu überspringen ? */
if( rows_to_skip != 0L )
skip_rows( out_channel, (rows_to_skip*360L)/v_dpi );
}
/*** Das war es: ***/
flush_block( out_channel );
return 0; /* Fehler sind nicht vorgesehen. */
}
/* Änderungen 7.10.95, M. Pristovsek */